//@author A0096440E
#include "TaskItScheduler.h"

TaskItScheduler::TaskItScheduler() {
}

void TaskItScheduler::setOwnerName(string owner) {
	_myStorage.readFile();
	_displayMode = EMPTY_FIELD;
}

string TaskItScheduler::initialWelcome(bool &smallUI) {
	Logger *_logFile;
	_logFile = Logger::getInstance();
	_logFile->clearLogFile();
	_displayVector.clear();
	ostringstream displayInfo;

	sprintf_s(buffer, MESSAGE_WELCOME.c_str());
	displayInfo << buffer;
	_logFile->loggingEvents(LOG_SCHEDULER_WELCOME);
	return displayInfo.str();
}

vector<string> TaskItScheduler::viewToday(bool &smallUI) {
	Date today;
	_displayVector.clear();
	_displayIndexes.clear();
	today.setLocalDate();

	for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
		if (!_myStorage.getTask(i).getDate().isLaterDate(today) && !_myStorage.getTask(i).getFloating() && !_myStorage.getTask(i).getDone()) {
			storeToDisplayVector(_myStorage.getTask(i), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
			_displayIndexes.push_back(i);
		}
	}

	viewDate(today.getDisplay(), smallUI);
	_displayMode = VIEW_INITIAL;
	return _displayVector;
}

vector <string> TaskItScheduler::executeCommand(string allInfo, bool &smallUI) {
	_displayVector.clear();
	assert(!allInfo.empty());
	assert(smallUI);
	try {
		_infoString.splitString(allInfo);
	} catch (string error) {
		_displayVector.push_back(error);
		return _displayVector;
	}

	CommandType commandType = determineCommandType(_infoString.getInfoNumber(SLOT_ZERO));
	string message;
	_previousCommand = _currentCommand;
	_currentCommand = commandType;
	Logger *_logFile;
	_logFile = Logger::getInstance();
	_logFile->loggingEvents(LOG_SCHEDULER_EXECUTE_COMMAND);
	
	switch (commandType) {
	case ADD_TASK:
		_displayVector.push_back(addTask(_infoString.getInfoNumber(SLOT_ONE), 
										 _infoString.getInfoNumber(SLOT_TWO), 
										 _infoString.getInfoNumber(SLOT_THREE), 
										 _infoString.getInfoNumber(SLOT_FOUR), 
										 _infoString.getInfoNumber(SLOT_FIVE), 
										 _infoString.getInfoNumber(SLOT_SIX)));
		return _displayVector;
	case DELETE_TASK:
		_displayVector.push_back(deleteTask(_infoString.getInfoNumber(SLOT_ONE)));
		return _displayVector;
	case F_DELETE_TASK:
		_displayVector.push_back(fDeleteTask(_infoString.getInfoNumber(SLOT_ONE)));
		return _displayVector;
	case EDIT_TASK:
		_displayVector.push_back(editTask(_infoString.getInfoNumber(SLOT_ONE), 
										  _infoString.getInfoNumber(SLOT_TWO), 
										  _infoString.getInfoNumber(SLOT_THREE), 
										  _infoString.getInfoNumber(SLOT_FOUR), 
										  _infoString.getInfoNumber(SLOT_FIVE), 
										  _infoString.getInfoNumber(SLOT_SIX), 
										  _infoString.getInfoNumber(SLOT_SEVEN)));
		return _displayVector;
	case F_EDIT_TASK:
		_displayVector.push_back(fEditTask(_infoString.getInfoNumber(SLOT_ONE), 
										   _infoString.getInfoNumber(SLOT_TWO), 
										   _infoString.getInfoNumber(SLOT_THREE), 
										   _infoString.getInfoNumber(SLOT_FOUR), 
										   _infoString.getInfoNumber(SLOT_FIVE), 
										   _infoString.getInfoNumber(SLOT_SIX), 
										   _infoString.getInfoNumber(SLOT_SEVEN)));
		return _displayVector;
	case VIEW_TASK:
		viewTask(_infoString.getInfoNumber(SLOT_ONE), smallUI);
		return _displayVector;
	case SEARCH_TASK:
		searchTask(_infoString.getInfoNumber(SLOT_ONE), smallUI);
		return _displayVector;
	case MARK_TASK:
		_displayVector.push_back(markTask(_infoString.getInfoNumber(SLOT_ONE)));
		return _displayVector;
	case UNMARK_TASK:
		_displayVector.push_back(unMarkTask(_infoString.getInfoNumber(SLOT_ONE)));
		return _displayVector;
	case BLOCK:
		_displayVector.push_back(block(_infoString.getInfoNumber(SLOT_ONE), 
									   _infoString.getInfoNumber(SLOT_TWO), 
									   _infoString.getInfoNumber(SLOT_THREE), 
									   _infoString.getInfoNumber(SLOT_FOUR), 
									   _infoString.getInfoNumber(SLOT_FIVE), 
									   _infoString.getInfoNumber(SLOT_SIX)));
		return _displayVector;
	case CONFIRM:
		_displayVector.push_back(confirm(_infoString.getInfoNumber(SLOT_ONE)));
		return _displayVector;
	case CLEAR:
		message = MESSAGE_CONFIRM_PERMANENT_CLEAR_ONE + MESSAGE_CONFIRM_PERMANENT_CLEAR_TWO;
		_displayVector.push_back(message);
		return _displayVector;
	case UNDO_TASK:
		_displayVector.push_back(undoTask());
		return _displayVector;
	case HELP:
		_displayVector.push_back(helpTask());
		return _displayVector;
	case YES:
		if (_previousCommand == CLEAR) {
			_displayVector.push_back(clearTasks());		
		} else {
			_displayVector.push_back(addConflictedTask());
		}
		return _displayVector;
	case NO:
		if (_previousCommand == CLEAR) {
			_displayVector.push_back(MESSAGE_NOT_CLEARED);
		} else {
			_displayVector.push_back(doNotAddConflictedTask());
		}
		return _displayVector;
	default:
		try {
			string activity, date;
			_specialStringParser.parseString(allInfo, activity, date);
			_displayVector.push_back(addTask(activity,
											 EMPTY_FIELD,
											 EMPTY_FIELD,
											 EMPTY_FIELD,
											 EMPTY_FIELD,
											 date));
			return _displayVector;
		} catch (string error) {
			_logFile->loggingEvents(error);
			_displayVector.push_back(error);
			return _displayVector;
		}
	}
}

string TaskItScheduler::clearTasks() {
	_myStorage.clearTasks();
	return MESSAGE_CLEARED;
}

bool TaskItScheduler::checkClash(TaskItTime newStartTime, TaskItTime newEndTime, TaskItTime currentStartTime, TaskItTime currentEndTime) {
	if (newStartTime.getHasTime() && newEndTime.getHasTime() && currentStartTime.getHasTime() && currentEndTime.getHasTime()) {
		if (newEndTime.isLaterTime(currentStartTime) && currentEndTime.isLaterTime(newStartTime)) {
			return true;
		}
	} else if (!newStartTime.getHasTime() && newEndTime.getHasTime() && currentStartTime.getHasTime() && currentEndTime.getHasTime()) {
		if (newEndTime.isLaterTime(currentStartTime) && currentEndTime.isLaterTime(newEndTime)) {
			return true;
		}
	} else if (newStartTime.getHasTime() && !newEndTime.getHasTime() && currentStartTime.getHasTime() && currentEndTime.getHasTime()) {
		if (newStartTime.isLaterTime(currentStartTime) && currentEndTime.isLaterTime(newStartTime)) {
			return true;
		}
	} else if (newStartTime.getHasTime() && newEndTime.getHasTime() && !currentStartTime.getHasTime() && currentEndTime.getHasTime()) {
		if (currentEndTime.isLaterTime(newStartTime) && newEndTime.isLaterTime(currentEndTime)) {
			return true;
		}
	} else if (newStartTime.getHasTime() && newEndTime.getHasTime() && currentStartTime.getHasTime() && !currentEndTime.getHasTime()) {
		if (currentStartTime.isLaterTime(newStartTime) && newEndTime.isLaterTime(currentStartTime)) {
			return true;
		}
	}
	return false;
}

void TaskItScheduler::checkValidTime(TaskItTime &time, string timeString) {
	Logger *_logFile;
	_logFile = Logger::getInstance();

	try {
		if (timeString != EMPTY_FIELD) {
			_logFile->loggingEvents(LOG_SCHEDULER_SET_TIME_SUCCESSFUL);
			time.setTime(timeString);
		}
	} catch (string error) {
		throw error;
	}
	return;
}

void TaskItScheduler::checkValidCombinationTime(TaskItTime &timeStart, TaskItTime &timeEnd, string timeStartString, string timeEndString) {
	Logger *_logFile;
	_logFile = Logger::getInstance();

	if (timeStartString != EMPTY_FIELD && timeEndString != EMPTY_FIELD) {
		if (timeStart.isLaterTime(timeEnd)) {
			_logFile->loggingEvents(LOG_SCHEDULER_INVALID_TIME_COMBINATION);
			throw INVALID_TIME_COMBINATION;
		}
	}
	return;
}

void TaskItScheduler::checkValidActivity(string activity) {
	Logger *_logFile;
	_logFile = Logger::getInstance();

	if (activity == EMPTY_FIELD) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_ADD);
		throw INVALID_ADD;
	}
	if (activity == BLOCK_FUNCTION_TWO) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_ADD);
		throw INVALID_USE_OF_BLOCK;
	}
	return;
}

void TaskItScheduler::checkValidDateWithTime(string date, string timeStartString, string timeEndString) {
	Logger *_logFile;
	_logFile = Logger::getInstance();

	if (date == EMPTY_FIELD && (timeStartString != EMPTY_FIELD || timeEndString != EMPTY_FIELD)) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_DATE_TIME);
		throw INVALID_DATE_TIME;
	}
	return;
}

void TaskItScheduler::checkValidDate(Date &newDate, string dateString, int date) {
	Logger *_logFile;
	_logFile = Logger::getInstance();

	try {
		if (dateString != EMPTY_FIELD) {
			_logFile->loggingEvents(LOG_SCHEDULER_SET_DATE_SUCCESSFUL);
			newDate.setDate(date);
		}
	} catch (string error) {
		throw error;
	}
}

string TaskItScheduler::addTask(string info2, string info3, string info4, string info5, string info6, string info7) {
	string activity, venue, timeStartString, timeEndString, category;
	TaskItTime timeStartOfPossibleClash, timeEndOfPossibleClash, timeStart, timeEnd;
	ostringstream displayInfo;
	int date;
	Logger *_logFile;
	_logFile = Logger::getInstance();

	activity = info2;
	venue = info3;
	timeStartString = info4;
	timeEndString = info5;
	category = info6;
	date = atoi(info7.c_str());
	
	try {
		checkValidTime(timeStart, timeStartString);
		checkValidTime(timeEnd, timeEndString);
		checkValidCombinationTime(timeStart, timeEnd, timeStartString, timeEndString);
		checkValidActivity(activity);
		checkValidDateWithTime(info7, timeStartString, timeEndString);
		Date newDate;
		checkValidDate(newDate, info7, date);
		for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
			if (_myStorage.getTask(i).getDate().isSameDate(newDate)) {
				if (checkClash(timeStart, timeEnd, _myStorage.getTask(i).getTimeStart(), _myStorage.getTask(i).getTimeEnd())) {
					_myStorage.addTempTask(activity, venue, timeStart, timeEnd, category, newDate);
					_logFile->loggingEvents(LOG_SCHEDULER_ADD_TEMP);
					sprintf_s(buffer, CLASH_FOUND.c_str());
					displayInfo << showToUser(buffer) << NEW_LINE << _myStorage.getTaskDetails(i);
					return displayInfo.str();
				}
			}
		}
		int index = _myStorage.addTask(activity, venue, timeStart, timeEnd, category, newDate);
		_logFile->loggingEvents(LOG_SCHEDULER_ADDED);
		sprintf_s(buffer, MESSAGE_ADDED.c_str());
		displayInfo << buffer << NEW_LINE << NEW_LINE << _myStorage.getTaskDetails(index);
		Date today;
		today.setLocalDate();
		if (today.isLaterDate(newDate) && newDate.getHasDate() &&!today.isSameDate(newDate)) {
			displayInfo << NEW_LINE << MESSAGE_ADDED_DATE_PAST;
		}
		return displayInfo.str();	
	} catch (string error) {
		_logFile->loggingEvents(error);
		return showToUser(error);
	}
}

string TaskItScheduler::addConflictedTask() {
	Logger *_logFile;
	_logFile = Logger::getInstance();
	int index;
	ostringstream displayInfo; 

	try {
		_myStorage.addConflictedTask(index);
		_logFile->loggingEvents(LOG_SCHEDULER_ADDED);
		sprintf_s(buffer, MESSAGE_ADDED.c_str());
		displayInfo << buffer << NEW_LINE << NEW_LINE << _myStorage.getTaskDetails(index);
		return displayInfo.str();
	} catch (string error) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_COMMAND);
		return error;
	}
}

string TaskItScheduler::doNotAddConflictedTask() {
	Logger *_logFile;
	_logFile = Logger::getInstance();
	
	try {
		_myStorage.doNotAddConflictedTask();
		_logFile->loggingEvents(LOG_SCHEDULER_NOT_ADDED);
		sprintf_s(buffer, NOT_ADDED.c_str());
		return showToUser(buffer);
	} catch (string error) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_COMMAND);
		return error;
	}
}

string TaskItScheduler::deleteTask(string info2) {
	ostringstream displayInfo;
	Logger *_logFile;
	_logFile = Logger::getInstance();

	int displayIndex = atoi(info2.c_str());
	int indexSize = _displayIndexes.size();
	
	if (displayIndex > indexSize || displayIndex <= BELOW_ZERO_INDEX) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_DELETE);
		sprintf_s(buffer, INVALID_DELETE.c_str());
		return showToUser(buffer);
	} else {
		int numOfTask = _displayIndexes[displayIndex - SHIFT_INDEX_BY_ONE];
		_logFile->loggingEvents(LOG_SCHEDULER_DELETED);
		sprintf_s(buffer, MESSAGE_DELETED.c_str());
		displayInfo << showToUser(buffer) << NEW_LINE << _myStorage.getTaskDetails(numOfTask);
		_myStorage.deleteTask(numOfTask + SHIFT_INDEX_BY_ONE);
		return displayInfo.str();
	}
}

string TaskItScheduler::fDeleteTask(string info2) {
	ostringstream displayInfo;
	Logger *_logFile;
	_logFile = Logger::getInstance();

	int floatingIndex = atoi(info2.c_str());

	if (floatingIndex > _myStorage.getNumOfFloatingTask() || floatingIndex <= BELOW_ZERO_INDEX) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_DELETE);
		sprintf_s(buffer, INVALID_DELETE.c_str());
		return showToUser(buffer);
	} else {
		_logFile->loggingEvents(LOG_SCHEDULER_DELETED);
		sprintf_s(buffer, MESSAGE_DELETED.c_str());
		displayInfo << showToUser(buffer) << NEW_LINE << _myStorage.getTaskDetails(floatingIndex - SHIFT_INDEX_BY_ONE);
		_myStorage.deleteTask(floatingIndex);
		return displayInfo.str();
	}
}

string TaskItScheduler::checkEditIndex(string indexString, bool &isValid) {
	assert(!indexString.empty());
	int indexSize = _displayIndexes.size();
	int displayIndex = atoi(indexString.c_str());
	
	if (displayIndex <= BELOW_ZERO_INDEX || displayIndex > indexSize) {
		return INVALID_REQUEST;
	} else {
		int index = _displayIndexes[displayIndex - SHIFT_INDEX_BY_ONE];
		if (index >= BELOW_ZERO_INDEX && index < _myStorage.getNumOfTask()) {
			isValid = true;
			size_t found;
			string activity = _myStorage.getTask(index).getActivity();
			found = activity.find(BLOCK_FUNCTION);

			if (found != string::npos) {
				activity.erase(activity.begin(), activity.begin() + SEVEN);
			}
			return _infoString.contentateFields(activity, 
												_myStorage.getTask(index).getVenue(), 
												_myStorage.getTask(index).getTimeStart().getOriginalDisplay(), 
												_myStorage.getTask(index).getTimeEnd().getOriginalDisplay(), 
												_myStorage.getTask(index).getCategory(), 
												_myStorage.getTask(index).getDate().getDisplay());
		} else {
			isValid = false;
			return INVALID_REQUEST;
		}
	}
}

string TaskItScheduler::editTask(string info2, string info3, string info4, string info5, string info6, string info7, string info8) {
	string activity, venue, timeStartString, timeEndString, category;
	TaskItTime timeStart, timeEnd;
	ostringstream displayInfo;
	int date, numOfTask, index, displayIndex, indexSize = _displayIndexes.size();
	Logger *_logFile;
	_logFile = Logger::getInstance();
	
	displayIndex = atoi(info2.c_str());
	activity = info3;
	venue = info4;
	timeStartString = info5;
	timeEndString = info6;
	category = info7;
	date = atoi(info8.c_str());
	
	if (displayIndex > indexSize || displayIndex <= BELOW_ZERO_INDEX) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_EDIT);
		sprintf_s(buffer, INVALID_EDIT.c_str());
		return showToUser(buffer);
	}
	numOfTask = _displayIndexes[displayIndex - SHIFT_INDEX_BY_ONE];
	
	

	try {
		checkValidActivity(activity);
		checkValidDateWithTime(info8, timeStartString, timeEndString);
		checkValidTime(timeStart, timeStartString);
		checkValidTime(timeEnd, timeEndString);
		checkValidCombinationTime(timeStart, timeEnd, timeStartString, timeEndString);
		Date newDate;
		checkValidDate(newDate, info8, date);
		size_t found;
		found = _myStorage.getTask(numOfTask).getActivity().find(BLOCK_FUNCTION);
		if (found != string::npos && newDate.getDisplay() == EMPTY_FIELD) {
			sprintf_s(buffer, INVALID_BLOCK.c_str());
			_logFile->loggingEvents(LOG_SCHEDULER_INVALID_EDIT);
			return showToUser(buffer);
		}
		for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
			if(_myStorage.getTask(i).getDate().isSameDate(newDate) && i != numOfTask) {
				if (checkClash(timeStart, timeEnd, _myStorage.getTask(i).getTimeStart(), _myStorage.getTask(i).getTimeEnd())) {
					sprintf_s(buffer, CLASH_FOUND_EDITED.c_str());
					_logFile->loggingEvents(LOG_SCHEDULER_EDITED_WHILE_CLASHED);
					index = _myStorage.editTask(activity, venue, timeStart, timeEnd, category, newDate, numOfTask + SHIFT_INDEX_BY_ONE);
					displayInfo << showToUser(buffer) << NEW_LINE << _myStorage.getTaskDetails(index) << NEW_LINE << CLASH_FOUND_UNDO;
					return displayInfo.str();
				}
			}
		}
		_logFile->loggingEvents(LOG_SCHEDULER_EDITED);
		sprintf_s(buffer, MESSAGE_EDITED.c_str());
		displayInfo << showToUser(buffer) << NEW_LINE << _myStorage.getTaskDetails(numOfTask) << TO;
		index = _myStorage.editTask(activity, venue, timeStart, timeEnd, category, newDate, numOfTask + SHIFT_INDEX_BY_ONE);
		ostringstream os;
		os << index;
		_logFile->loggingEvents(os.str());
		displayInfo << NEW_LINE << NEW_LINE << _myStorage.getTaskDetails(index);
		return displayInfo.str(); 
	} catch (string error) {
		_logFile->loggingEvents(error);
		return showToUser(error);
	}
}

string TaskItScheduler::checkFEditIndex(string indexString, bool &isValid) {
	assert(!indexString.empty());
	int floatingIndex = atoi(indexString.c_str());
	
	if (floatingIndex <= BELOW_ZERO_INDEX || floatingIndex > _myStorage.getNumOfFloatingTask()) {
		isValid = false;
		return INVALID_REQUEST;
	} else {
		isValid = true;
		return _infoString.contentateFields(_myStorage.getTask(floatingIndex - SHIFT_INDEX_BY_ONE).getActivity(), 
											_myStorage.getTask(floatingIndex - SHIFT_INDEX_BY_ONE).getVenue(), 
											_myStorage.getTask(floatingIndex - SHIFT_INDEX_BY_ONE).getTimeStart().getOriginalDisplay(), 
											_myStorage.getTask(floatingIndex - SHIFT_INDEX_BY_ONE).getTimeEnd().getOriginalDisplay(), 
											_myStorage.getTask(floatingIndex - SHIFT_INDEX_BY_ONE).getCategory(), 
											_myStorage.getTask(floatingIndex - SHIFT_INDEX_BY_ONE).getDate().getDisplay());
	}
}

string TaskItScheduler::fEditTask(string info2, string info3, string info4, string info5, string info6, string info7, string info8) {
	string activity, venue, timeStartString, timeEndString, category;
	TaskItTime timeStart, timeEnd;
	ostringstream displayInfo;
	int date, index, floatingIndex;
	Logger *_logFile;
	_logFile = Logger::getInstance();

	floatingIndex = atoi(info2.c_str());
	activity = info3;
	venue = info4;
	timeStartString = info5;
	timeEndString = info6;
	category = info7;
	date = atoi(info8.c_str());
	
	if (floatingIndex > _myStorage.getNumOfFloatingTask() || _myStorage.getNumOfFloatingTask() <= BELOW_ZERO_INDEX || 
		floatingIndex <= BELOW_ZERO_INDEX) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_EDIT);
		sprintf_s(buffer, INVALID_EDIT.c_str());
		return showToUser(buffer);
	}
	try {
		checkValidActivity(activity);
		checkValidDateWithTime(info8, timeStartString, timeEndString);
		checkValidTime(timeStart, timeStartString);
		checkValidTime(timeEnd, timeEndString);
		checkValidCombinationTime(timeStart, timeEnd, timeStartString, timeEndString);
		Date newDate;
		checkValidDate(newDate, info8, date);
		for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
			if (_myStorage.getTask(i).getDate().isSameDate(newDate) && i != floatingIndex - SHIFT_INDEX_BY_ONE) {
				if (checkClash(timeStart, timeEnd, _myStorage.getTask(i).getTimeStart(), _myStorage.getTask(i).getTimeEnd())) {
					sprintf_s(buffer, CLASH_FOUND_EDITED.c_str());
					_logFile->loggingEvents(LOG_SCHEDULER_EDITED_WHILE_CLASHED);
					index = _myStorage.editTask(activity, venue, timeStart, timeEnd, category, newDate, floatingIndex);
					displayInfo << showToUser(buffer) << NEW_LINE << _myStorage.getTaskDetails(index) << NEW_LINE << CLASH_FOUND_UNDO;
					return displayInfo.str();
				}
			}
		}
		_logFile->loggingEvents(LOG_SCHEDULER_EDITED);
		sprintf_s(buffer, MESSAGE_EDITED.c_str());
		displayInfo << showToUser(buffer) << NEW_LINE << _myStorage.getTaskDetails(floatingIndex - SHIFT_INDEX_BY_ONE) << TO;
		index = _myStorage.editTask(activity, venue, timeStart, timeEnd, category, newDate, floatingIndex);
		ostringstream os;
		os << index;
		_logFile->loggingEvents(os.str());
		displayInfo << NEW_LINE << NEW_LINE << _myStorage.getTaskDetails(index);
		return displayInfo.str();
	} catch (string error) {
		_logFile->loggingEvents(error);
		return showToUser(error);
	}
}

//@author A0096509U
void TaskItScheduler::viewTask(string info2, bool &smallUI) {
	string viewFormat;
	Logger *_logFile;
	_logFile = Logger::getInstance();
	
	_displayIndexes.clear();
	viewFormat = info2;
    _logFile->loggingEvents(LOG_SCHEDULER_SIFTING_VIEW);
	
	if (viewFormat == VIEW_ALL) {
		return viewAll(smallUI);
	} else if (viewFormat[FIRST_CHARACTER] <= NUM_9 && viewFormat[FIRST_CHARACTER] >= NUM_0) {
		return viewDate(info2, smallUI);
	} else {
		return viewCategory(info2, smallUI);
	}
}

void TaskItScheduler::storeToDisplayVector(Task task, int index) {
	ostringstream indexString;
	indexString << index;

	_displayVector.push_back(indexString.str());
	_displayVector.push_back(task.getActivity());
	_displayVector.push_back(task.getVenue());
	_displayVector.push_back(task.getTimeStart().getDisplay());
	_displayVector.push_back(task.getTimeEnd().getDisplay());
	_displayVector.push_back(task.getCategory());
	_displayVector.push_back(task.getDate().getDisplay());
	if (task.getDone()) {
		_displayVector.push_back(DISPLAY_DONE);
	} else {
		_displayVector.push_back(DISPLAY_NOT_DONE);
	}
	return;
}

void TaskItScheduler::viewDate(string info2, bool &smallUI) {
	int date;
	Logger *_logFile;
	_logFile = Logger::getInstance();
	
	date = atoi(info2.c_str());

	try {
		Date myDate;
		myDate.setDate(date);
		for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
			if (_myStorage.getTask(i).getDate().isSameDate(myDate) && !_myStorage.getTask(i).getFloating()) {
				storeToDisplayVector(_myStorage.getTask(i), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
				_displayIndexes.push_back(i);
			}
		}
		_displayMode = info2;
		if (_displayVector.empty()) {
			_logFile->loggingEvents(LOG_SCHEDULER_NO_VIEW);
			sprintf_s(buffer, VIEW_NOTHING.c_str());
			_displayVector.push_back(buffer);
		} else {
			smallUI = false;
			_logFile->loggingEvents(LOG_SCHEDULER_VIEW);
		}
	} catch (string error) {
		_logFile->loggingEvents(error);
		_displayVector.push_back(error);
	}
}

void TaskItScheduler::viewCategory(string info2, bool &smallUI) {
	string category;
	Logger *_logFile;
	_logFile = Logger::getInstance();
	
	category = info2;

	for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
		if (_myStorage.getTask(i).getCategory() == category &&  !_myStorage.getTask(i).getDone()) {
			storeToDisplayVector(_myStorage.getTask(i), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
			_displayIndexes.push_back(i);
		}
	}
	for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
		if (_myStorage.getTask(i).getCategory() == category &&  _myStorage.getTask(i).getDone()) {
			storeToDisplayVector(_myStorage.getTask(i), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
			_displayIndexes.push_back(i);
		}
	}
	_displayMode = category;
	if (_displayVector.empty()) {
		_logFile->loggingEvents(LOG_SCHEDULER_NO_VIEW);
		sprintf_s(buffer, INVALID_VIEW.c_str());
		_displayVector.push_back(buffer);
	} else {
		smallUI = false;
		_logFile->loggingEvents(LOG_SCHEDULER_VIEW);
	}
}

void TaskItScheduler::viewAll(bool &smallUI) {
	Logger *_logFile;
	_logFile = Logger::getInstance();
	Date today;
	today.setLocalDate();
	
	for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
		if (!_myStorage.getTask(i).getDate().isLaterDate(today) && !_myStorage.getTask(i).getFloating() && !_myStorage.getTask(i).getDone()) {
			storeToDisplayVector(_myStorage.getTask(i), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
			_displayIndexes.push_back(i);
		}
	}
	for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
		if ((_myStorage.getTask(i).getDate().isSameDate(today) || _myStorage.getTask(i).getDate().isLaterDate(today)) && !_myStorage.getTask(i).getFloating()) {
			storeToDisplayVector(_myStorage.getTask(i), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
			_displayIndexes.push_back(i);
		}
	}
	for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
		if (!_myStorage.getTask(i).getDate().isLaterDate(today) && !_myStorage.getTask(i).getFloating() && _myStorage.getTask(i).getDone()) {
			storeToDisplayVector(_myStorage.getTask(i), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
			_displayIndexes.push_back(i);
		}
	}
	_displayMode = VIEW_ALL;
	if (_displayVector.empty()) {
		_logFile->loggingEvents(LOG_SCHEDULER_NO_VIEW);
		sprintf_s(buffer, VIEW_NOTHING.c_str());
		_displayVector.push_back(buffer);
	} else {
		smallUI = false;
		_logFile->loggingEvents(LOG_SCHEDULER_VIEW);
	}
}

vector <string> TaskItScheduler::refreshBigWindow(bool &smallUI) {
	_displayVector.clear();
	_displayIndexes.clear();
	if (_displayMode == VIEW_INITIAL) {
		return viewToday(smallUI);
	} else if (_displayMode == SEARCH) {
		searchTask(_keyword, smallUI);
	} else {
		viewTask(_displayMode, smallUI);
	}
	return _displayVector;
}

string TaskItScheduler::refreshFloatingTasksWindow() {
	ostringstream displayInfo;
	for (int i = INITIAL_VALUE; i < _myStorage.getNumOfTask(); i++) {
		if (_myStorage.getTask(i).getFloating()) {
			displayInfo << i + SHIFT_INDEX_BY_ONE << DOT << WHITE_SPACE << _myStorage.getTask(i).getActivity();
			if (_myStorage.getTask(i).getVenue() != EMPTY_FIELD) {
				displayInfo << WHITE_SPACE << OPEN_SQUARE_BRACKET << DISPLAY_VENUE << 
				_myStorage.getTask(i).getVenue() << CLOSED_SQUARE_BRACKET;
			}
			if (_myStorage.getTask(i).getCategory() != EMPTY_FIELD) {
				displayInfo << WHITE_SPACE << OPEN_SQUARE_BRACKET << DISPLAY_CATEGORY <<
				_myStorage.getTask(i).getCategory() << CLOSED_SQUARE_BRACKET;
			}
			displayInfo << NEW_LINE;
		}
	}
	return displayInfo.str();
}

//@author A0096440E
void TaskItScheduler::searchTask(string info2, bool &smallUI) {
	Logger *_logFile;
	_logFile = Logger::getInstance();
	_displayVector.clear();
	_displayIndexes.clear();
	if (info2.empty()) {
		sprintf_s(buffer, INVALID_SEARCH.c_str());
		_logFile->loggingEvents(LOG_SCHEDULER_NOT_FOUND);
		_displayVector.push_back(buffer);
		return;
	}

	string keyword = info2;
	int size = _myStorage.getNumOfTask();
	bool searchFound = false;
	size_t found;
	string keywordWithCaps = keyword;

	_logFile->loggingEvents(LOG_SCHEDULER_SEARCHED);
	if (keywordWithCaps[INITIAL_VALUE] > SMALL_A && keywordWithCaps[INITIAL_VALUE] < SMALL_Z) {
		keywordWithCaps[INITIAL_VALUE] = CAPS_A + keywordWithCaps[INITIAL_VALUE] - SMALL_A;
	} else if (keywordWithCaps[INITIAL_VALUE] > CAPS_A && keywordWithCaps[INITIAL_VALUE] < CAPS_Z) {
		keywordWithCaps[INITIAL_VALUE] = SMALL_A + keywordWithCaps[INITIAL_VALUE] - CAPS_A;
	}

	for (int i = ONE_STARTING_VALUE; i <= size; i++) {
		found = _myStorage.getTask(i - SHIFT_INDEX_BY_ONE).getActivity().find(keyword);
		if (found != string::npos) {
			storeToDisplayVector(_myStorage.getTask(i - SHIFT_INDEX_BY_ONE), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
			_displayIndexes.push_back(i - SHIFT_INDEX_BY_ONE);
			searchFound = true;
		} else {
			found = _myStorage.getTask(i - SHIFT_INDEX_BY_ONE).getActivity().find(keywordWithCaps);
			if (found != string::npos) {
				storeToDisplayVector(_myStorage.getTask(i - SHIFT_INDEX_BY_ONE), _displayIndexes.size() + SHIFT_INDEX_BY_ONE);
				_displayIndexes.push_back(i - SHIFT_INDEX_BY_ONE);
				searchFound = true;
			}
		}
	}
	_displayMode = SEARCH;
	_keyword = keyword;

	if (searchFound) {
		smallUI = false;
		_logFile->loggingEvents(LOG_SCHEDULER_FOUND);
	} else {
		sprintf_s(buffer, INVALID_SEARCH.c_str());
		_logFile->loggingEvents(LOG_SCHEDULER_NOT_FOUND);
		_displayVector.push_back(buffer);
	}
}

string TaskItScheduler::markTask(string info2) {
	int numOfTask, displayIndex, indexSize = _displayIndexes.size();
	Logger *_logFile;
	_logFile = Logger::getInstance();
	ostringstream displayInfo;

	displayIndex = atoi(info2.c_str());

	if (displayIndex > indexSize || displayIndex <= BELOW_ZERO_INDEX) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_MARK);
		sprintf_s(buffer, INVALID_MARK.c_str());
		return showToUser(buffer);
	} else {
		numOfTask = _displayIndexes[displayIndex - SHIFT_INDEX_BY_ONE];
		Task task;
		task = _myStorage.getTask(numOfTask);
		if (task.getDone()) {
			sprintf_s(buffer, INVALID_ALREADY_MARKED.c_str());
			return showToUser(buffer);
		} else {
			_myStorage.markTask(numOfTask + SHIFT_INDEX_BY_ONE);
			_logFile->loggingEvents(LOG_SCHEDULER_MARK);
			sprintf_s(buffer, MESSAGE_MARKED.c_str());
			displayInfo << buffer << NEW_LINE << NEW_LINE << _myStorage.getTaskDetails(numOfTask);
			return displayInfo.str();
		}
	}
}

string TaskItScheduler::unMarkTask(string info2) {
	int numOfTask, displayIndex, indexSize = _displayIndexes.size();
	Logger *_logFile;
	_logFile = Logger::getInstance();
	ostringstream displayInfo;

	displayIndex = atoi(info2.c_str());

	if (displayIndex > indexSize || displayIndex <= BELOW_ZERO_INDEX) {
		_logFile->loggingEvents(LOG_SCHEDULER_INVALID_UNMARK);
		sprintf_s(buffer, INVALID_UNMARK.c_str());
		return showToUser(buffer);
	} else {
		numOfTask = _displayIndexes[displayIndex - SHIFT_INDEX_BY_ONE];
		Task task;
		task = _myStorage.getTask(numOfTask);
		if (!task.getDone()) {
			sprintf_s(buffer, INVALID_ALREADY_UNMARKED.c_str());
			return showToUser(buffer);
		} else {
			_myStorage.unMarkTask(numOfTask + SHIFT_INDEX_BY_ONE);
			_logFile->loggingEvents(LOG_SCHEDULER_UNMARK);
			sprintf_s(buffer, MESSAGE_UNMARKED.c_str());
			displayInfo << buffer << NEW_LINE << NEW_LINE << _myStorage.getTaskDetails(numOfTask);
			return displayInfo.str();
		}
	}
}

string TaskItScheduler::block(string info2, string info3, string info4, string info5, string info6, string info7) {
	string activity;
	activity = BLOCK_FUNCTION + info2;

	try {
		checkValidActivity(info2);
	} catch (string error) {
		return showToUser(error);
	}
	if (info7 == EMPTY_FIELD) {
		sprintf_s(buffer, INVALID_BLOCK.c_str());
		return showToUser(buffer);
	}
	return addTask(activity, info3, info4, info5, info6, info7);
	
}

string TaskItScheduler::confirm(string info2) {
	int numOfTask, displayIndex, indexSize = _displayIndexes.size();
	ostringstream displayInfo;
	displayIndex = atoi(info2.c_str());
	
	if (displayIndex > indexSize || displayIndex <= BELOW_ZERO_INDEX) {
		sprintf_s(buffer, INVALID_CONFIRM.c_str());
		return showToUser(buffer);
	} else {
		numOfTask = _displayIndexes[displayIndex - SHIFT_INDEX_BY_ONE];
		Task task;
		task = _myStorage.getTask(numOfTask);
		string activity = task.getActivity();
		if (activity.substr(SLOT_ZERO,SLOT_SEVEN)!= BLOCK_FUNCTION) {
			sprintf_s(buffer, INVALID_CONFIRM_TASK.c_str());
			return showToUser(buffer);
		} else {
			Task newTask = _myStorage.getTask(numOfTask);
			newTask.editTask(newTask.getActivity().substr(SLOT_SEVEN),
							 newTask.getVenue(), 
							 newTask.getTimeStart(), 
							 newTask.getTimeEnd(),
							 newTask.getCategory(), 
							 newTask.getDate());
			_myStorage.confirm(numOfTask + SHIFT_INDEX_BY_ONE);
			sprintf_s(buffer, MESSAGE_CONFIRM.c_str());
			displayInfo << buffer << NEW_LINE << NEW_LINE << newTask.getAllDetails();
			return displayInfo.str();
		}
	}
}

string TaskItScheduler::undoTask() {
	Logger *_logFile;
	_logFile = Logger::getInstance();
	
	_logFile->loggingEvents(LOG_SCHEDULER_UNDO);
	try {
		_myStorage.undoTask();
		return showToUser(MESSAGE_UNDO);
	} catch (string error) {
		return error;
	}
}

string TaskItScheduler::helpTask() {
	Logger *_logFile;
	_logFile = Logger::getInstance();
	
	_logFile->loggingEvents(LOG_SCHEDULER_HELP);
	sprintf_s(buffer, LIST_OF_COMMANDS.c_str());
	return showToUser(buffer);
}

string TaskItScheduler::showToUser(string info) {
	ostringstream displayInfo;
	
	displayInfo << info << NEW_LINE;

	return displayInfo.str();
}

vector <int> TaskItScheduler::getDatesWithTasks() {
	return _myStorage.getDatesWithTasks();
}

CommandType TaskItScheduler::determineCommandType(string command) {
	Logger *_logFile;
	_logFile = Logger::getInstance();
	
	_logFile->loggingEvents(LOG_SCHEDULER_SIFTING_COMMAND);
	if (command == COMMAND_ADD) {
		return ADD_TASK;
	} else if (command == COMMAND_DELETE) {
		return CommandType::DELETE_TASK;
	} else if (command == COMMAND_F_DELETE) {
		return CommandType::F_DELETE_TASK;
	} else if (command == COMMAND_EDIT) {
		return CommandType::EDIT_TASK;
	} else if (command == COMMAND_F_EDIT) {
		return CommandType::F_EDIT_TASK;
	} else if (command == COMMAND_VIEW) {
		return CommandType::VIEW_TASK;
	} else if (command == COMMAND_SEARCH) {
		return CommandType::SEARCH_TASK;
	} else if (command == COMMAND_MARK) {
		return CommandType::MARK_TASK;
	} else if (command == COMMAND_UNMARK) {
		return CommandType::UNMARK_TASK;
	} else if (command == COMMAND_UNDO) {
		return CommandType::UNDO_TASK;
	} else if (command == COMMAND_HELP) {
		return CommandType::HELP;
	} else if (command == COMMAND_BLOCK) {
		return CommandType::BLOCK;
	} else if (command == COMMAND_CONFIRM) {
		return CommandType::CONFIRM;
	} else if (command == COMMAND_CLEAR) {
		return CommandType::CLEAR;
	} else if (command == COMMAND_YES) {
		return CommandType::YES;
	} else if (command == COMMAND_NO) {
		return CommandType::NO;
	} else {
	 	return CommandType::INVALID;
	}	
}